
/**
* @1900-2100区间内的公历
* @charset UTF-8
* @Author  iRacer 杨
* @Time    2020-5-2
* @Version 2.0.1
*/

Vue.component('datepicker', {
    template: '<div><datepicker-input :id="id" :data="val" @click="click"></datepicker-input><datepicker-dropdown :id="bid" :sdate="sdate" :cdate="cdate" :style="ddstyle" @choose="choose" @settoday="settoday" @clear="clear"></datepicker-dropdown></div>',
    props: {
        value: { type: String, default: "" },
        format: { type: String, default: "yyyy-MM-dd" }
    },
    data: function () {
        return {
            sdate: { y: 1900, m: 0, d: 1, h: 0, mm: 0, s: 0 },
            cdate: { y: 1900, m: 0, d: 1, h: 0, mm: 0, s: 0 },
            id: FLOATING_LAYER.guid(),
            bid: "",
            val: "",
            ddstyle: ""
        };
    },
    mounted: function() { this.init(); },
    methods: {
        init: function () {
            this.bid = FLOATING_LAYER.key + this.id;
            FLOATING_LAYER.list.push(this.id);
            this.initFormat();
        },
        initFormat: function () {
            // set date
            if (this.value && this.value.length >= 8) {
                var arr = this.value.replace(' ', '-').replace(':', '-').replace(':', '-').split('-');
                if (arr && arr.length > 0) { this.sdate.y = parseInt(arr[0]); }
                if (arr && arr.length > 1) { this.sdate.m = parseInt(arr[1]) - 1; }
                if (arr && arr.length > 2) { this.sdate.d = parseInt(arr[2]); }
                if (arr && arr.length > 3) { this.sdate.h = parseInt(arr[3]); }
                if (arr && arr.length > 4) { this.sdate.mm = parseInt(arr[4]); }
                if (arr && arr.length > 5) { this.sdate.s = parseInt(arr[5]); }
                this.setcurrent();
                this.formatShow();
            } else {
                this.setEmpty();
            }
        },
        choose: function (sdate) {
            this.sdate = sdate;
            this.setcurrent();
            this.formatShow();
            this.value = this.val;
            this.$emit("input", this.value);
        },
        setcurrent: function () {
            this.cdate.y = this.sdate.y;
            this.cdate.m = this.sdate.m;
            this.cdate.d = this.sdate.d;
            this.cdate.h = this.sdate.h;
            this.cdate.mm = this.sdate.mm;
            this.cdate.s = this.sdate.s;
        },
        formatShow: function () {
            var val = this.sdate.y + "-" + zeroPad(this.sdate.m + 1) + "-" + zeroPad(this.sdate.d);
            if(this.format === "yyyy-MM-dd HH:mm:ss") {
                val += " " + zeroPad(this.sdate.h) + ":" + zeroPad(this.sdate.mm) + ":" + zeroPad(this.sdate.s);
                this.val = val;
            } else if(this.format === "yyyy-MM-dd"){
                this.val = val;
            } else {
                console.error("日期格式错误,只支持\"yyyy-MM-dd\"和\"yyyy-MM-dd HH:mm:ss\" ");
            }
            
            // 日期补零
            function zeroPad(n) {
                n = parseInt(n);
                return String(n < 10 ? '0' + n : n);
            }
        },
        click: function (ddstyle) {
            this.ddstyle = ddstyle;
        },
        setEmpty: function () {
            var cdate = new Date();
            this.sdate.y = cdate.getFullYear();
            this.sdate.m = cdate.getMonth();
            this.sdate.d = cdate.getDate();
            this.sdate.h = cdate.getHours();
            this.sdate.mm = cdate.getMinutes();
            this.sdate.s = cdate.getSeconds();
            this.setcurrent();
        },
        settoday: function () {
            this.setEmpty();
            this.formatShow();
            this.value = this.val;
            this.$emit("input", this.value);
        },
        clear: function () {
            this.setEmpty();
            this.value = "";
            this.val = "";
            this.$emit("input", this.value);
        }
    }
});
Vue.component('datepicker-input', {
    template: '<div class="input-group date" @click="click" :id="id"><input type="text" class="form-control" v-model="data" readonly="readonly"><span class="input-group-addon"><i class="fa fa-calendar"></i></span></div>',
    props: {
        data: { type: Object, default: null },
        id: { type: String, default: "" }
    },
    data: function () {
        return {
            loaded: false
        };
    },
    methods: {
        click: function ($event) {
            if ($event !== undefined) {
                $event.stopPropagation();
            }
            var picker = $event.currentTarget;
            var height = picker.offsetHeight;
            var offset = FLOATING_LAYER.getElementOffSet(picker);
            var style = "z-index:10;top:" + (offset.top + height) + "px;left:" + (offset.left + 5) + "px;";
            var bid = FLOATING_LAYER.key + this.id;
            var datepicker = document.getElementById(bid);
            if (datepicker) {
                if (!this.loaded) {
                    this.loaded = true;
                    document.getElementById("app").appendChild(datepicker);
                }
                datepicker.style.display = "block";
            }
            this.$emit("click", style);
        }
    }
});
Vue.component('datepicker-dropdown', {
    template: '<div :id="id" :class="cname" :style="style"><datepicker-days :id="id" :sdate="sdate" :cdate="cdate" @choose="choose" @switcht="switcht" @settoday="settoday" @clear="clear" v-show="type===1"/><datepicker-months :sdate="sdate" :cdate="cdate" @choose="choose" @switcht="switcht" @back="back" v-show="type===2"/> <datepicker-years :sdate="sdate" :cdate="cdate" @choose="choose" @switcht="switcht" @back="back" v-show="type===3"/><datepicker-time :id="id" :sdate="sdate" @choose="choose" @switcht="switcht" @back="back" v-show="type===4"/></div>',
    props: {
        sdate: { type: Object, default: { y: 1900, m: 0, d: 1 } },
        cdate: { type: Object, default: { y: 1900, m: 0, d: 1 } },
        style: { type: String, default: "" },
        id: { type: String, default: "" }
    },
    data: function () {
        return {
            type: 1,
            cname: "datepicker datepicker-dropdown dropdown-menu datepicker-orient-left datepicker-orient-top"
        };
    },
    methods: {
        choose: function (sdate, type) {
            this.sdate = sdate;
            if (type === 1 || type === 4) {
                this.type = 1;
                this.$emit("choose", sdate);
            } else if (type === 2 || type === 3) {
                this.type--;
            }
        },
        switcht: function (type) {
            if (type === 3) { return false; }
            if (type === 4) { this.type = 4; return false; }
            this.type = type + 1;
        },
        settoday: function () {
            this.$emit("settoday");
        },
        clear: function () {
            this.$emit("clear");
        },
        back: function (type) {
            this.type = type - 1;
        }
    }
});
Vue.component('datepicker-years', {
    template: '<div class="datepicker-years" style="display: block;"><table class="table-condensed"><thead><tr><th class="prev" style="visibility: visible;" @click="prev">«</th><th colspan="5" class="datepicker-switch" @click="switcht">{{sdate.y - 5}}-{{sdate.y + 6}}</th><th class="next" style="visibility: visible;" @click="next">»</th></tr></thead><tbody><tr><td  colspan="7"><span v-for="item in years" @click="choose(item.y)" :class="item.c">{{item.y}}</span></td></tr></tbody><tfoot><tr><th colspan="7" class="today" style="display: table-cell;" @click="back">返回</th></tr></tfoot></table></div>',
    props: {
        sdate: { type: Object, default: { y: 1900, m: 0, d: 1 } },
        cdate: { type: Object, default: { y: 1900, m: 0, d: 1 } }
    },
    data: function () {
        return {
            years: []
        };
    },
    watch: {
        "sdate.y": { handler() { this.render(); }, deep: false },
        "cdate.y": { handler() { this.render(); }, deep: false }
    },
    mounted: function () {
        this.render();
    },
    methods: {
        render: function () {
            this.years = [];
            for (var i = 0; i < 12; i++) {
                var item = { y: this.sdate.y - 5 + i, c: "year" };
                item.c += item.y === this.cdate.y ? " active" : "";
                this.years.push(item);
            }
        },
        choose: function (y) {
            this.sdate.y = y;
            this.$emit("choose", this.sdate, 3);
        },
        prev: function () {
            this.sdate.y -= 12;
            this.render();
        },
        switcht: function () {
            this.$emit("switcht", 3);
        },
        back: function () {
            this.$emit("back", 3);
        },
        next: function () {
            this.sdate.y += 12;
            this.render();
        }
    }
});
Vue.component('datepicker-months', {
    template: '<div class="datepicker-months" style="display: block;"><table class="table-condensed"><thead><tr><th class="prev" style="visibility: visible;" @click="prev">«</th><th colspan="5" class="datepicker-switch" @click="switcht">{{sdate.y}}</th><th class="next" style="visibility: visible;" @click="next">»</th></tr></thead><tbody><tr><td  colspan="7"><span v-for="item in months" @click="choose(item.m)" :class="item.c">{{nmonths[item.m]}}</span></td></tr></tbody><tfoot><tr><th colspan="7" class="today" style="display: table-cell;" @click="back">返回</th></tr></tfoot></table></div>',
    props: {
        sdate: { type: Object, default: { y: 1900, m: 0, d: 1 } },
        cdate: { type: Object, default: { y: 1900, m: 0, d: 1 } }
    },
    data: function () {
        return {
            nmonths: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一", "十二"],
            months: []
        };
    },
    watch: {
        "sdate.y": { handler() { this.render(); }, deep: false },
        "cdate.y": { handler() { this.render(); }, deep: false },
        "cdate.m": { handler() { this.render(); }, deep: false }
    },
    mounted: function () {
        this.render();
    },
    methods: {
        render: function () {
            this.months = [];
            for (var i = 0; i < 12; i++) {
                var item = { y: this.sdate.y, m: i, c: "month" };
                item.c += item.y === this.cdate.y && item.m === this.cdate.m ? " active" : "";
                this.months.push(item);
            }
        },
        choose: function (m) {
            this.sdate.m = m;
            this.$emit("choose", this.sdate, 2);
        },
        prev: function () {
            this.sdate.y--;
            this.render();
        },
        switcht: function () {
            this.$emit("switcht", 2);
        },
        back: function () {
            this.$emit("back", 2);
        },
        next: function () {
            this.sdate.y++;
            this.render();
        }
    }
});
Vue.component('datepicker-days', {
    template: '<div class="datepicker-days" style="display: block;"><table class="table-condensed"><thead><tr><th class="prev" style="visibility: visible;" @click="prev">«</th><th colspan="5" class="datepicker-switch" @click="switcht">{{switchlabel}}</th><th class="next" style="visibility: visible;" @click="next">»</th></tr><tr><th class="dow" v-for="w in weeks">{{w}}</th></tr></thead><tbody><tr><td v-for="item in days.d0" :class="item.c" @click="choose(item)">{{item.d}}</td></tr><tr><td v-for="item in days.d1" :class="item.c" @click="choose(item)">{{item.d}}</td></tr><tr><td v-for="item in days.d2" :class="item.c" @click="choose(item)">{{item.d}}</td></tr><tr><td v-for="item in days.d3" :class="item.c" @click="choose(item)">{{item.d}}</td></tr><tr><td v-for="item in days.d4" :class="item.c" @click="choose(item)">{{item.d}}</td></tr><tr><td v-for="item in days.d5" :class="item.c" @click="choose(item)">{{item.d}}</td></tr><tr><td v-for="item in days.d6" :class="item.c" @click="choose(item)">{{item.d}}</td></tr></tbody><tfoot><tr><th class="today" style="display: table-cell;" @click="settime"><span class="fa fa-clock-o"><span></th><th colspan="3" class="today" style="display: table-cell;" @click="settoday">今天</th><th colspan="3" class="clear" style="display: table-cell;" @click="clear">清空</th></tr></tfoot></table></div>',
    props: {
        id: { type: String, default: "" },
        sdate: { type: Object, default: { y: 1900, m: 0, d: 1 } },
        cdate: { type: Object, default: { y: 1900, m: 0, d: 1 } }
    },
    data: function () {
        return {
            days: { d0: [], d1: [], d2: [], d3: [], d4: [], d5: [] },
            months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一", "十二"],
            weeks: ['日', '一', '二', '三', '四', '五', '六'],
            switchlabel: ""
        };
    },
    watch: {
        "sdate.y": { handler() { this.render(); }, deep: false },
        "sdate.m": { handler() { this.render(); }, deep: false }
    },
    mounted: function () {
        this.render();
    },
    methods: {
        render: function () {
            var self = this;
            self.switchlabel = self.months[self.sdate.m] + " " + self.sdate.y;
            self.days = { d0: [], d1: [], d2: [], d3: [], d4: [], d5: [] };
            var start = first();
            var last = new Date(this.sdate.y, this.sdate.m + 1, 0).getDate();    //当月最后一天
            second(start, last);
            third();

            function first() {
                var firstdate = new Date(self.sdate.y, self.sdate.m, 1);
                var day = firstdate.getDay(); // 返回星期几（0～6）
                var items = [];
                if (day > 0) {
                    var prevmonth = new Date(firstdate);
                    prevmonth.setDate(prevmonth.getDate() - 1);
                    var lastdate = prevmonth.getDate();
                    for (var i = day; i--;) {
                        items.push({ d: lastdate - i, m: prevmonth.getMonth(), y: prevmonth.getFullYear(), c: "old day" });
                    }
                }
                var j = 1;
                for (; items.length < 7; j++) {
                    items.push({ d: j, m: self.sdate.m, y: self.sdate.y, c: (self.cdate.y === self.sdate.y && self.cdate.m === self.sdate.m && self.sdate.d === j) ? "active day" : "day" });
                }
                self.days.d0 = items;
                return j;
            }
            function second(start, last) {
                var i = 1, arr = [];
                for (; start <= last;) {
                    arr.push({ d: start++, m: self.sdate.m, y: self.sdate.y, c: (self.cdate.y === self.sdate.y && self.cdate.m === self.sdate.m && self.sdate.d === (start - 1)) ? "active day" : "day" });
                    if (arr.length === 7) {
                        self.days["d" + i] = [].concat(arr);
                        i++;
                        arr = [];
                    } else if ((i === 4 || i === 5) && start > last) {
                        self.days["d" + i] = arr;
                        break;
                    }
                }
            }
            function third() {
                var y = self.sdate.y + (self.sdate.m === 11 ? 1 : 0);
                var m = self.sdate.m === 11 ? 0 : (self.sdate.m + 1);

                var j = 1;
                var arr = [], len = self.days.d4.length;
                for (; len < 7; len++) {
                    arr.push({ d: j, m: m, y: y, c: "new day" });
                    j++;
                }
                self.days.d4 = self.days.d4.concat(arr);

                arr = [];
                len = self.days.d5.length;
                for (; len < 7; len++) {
                    arr.push({ d: j, m: m, y: y, c: "new day" });
                    j++;
                }
                self.days.d5 = self.days.d5.concat(arr);
            }
        },
        choose: function (item) {
            if (this.sdate.y === item.y && this.sdate.m === item.m) {
                this.hide();
                this.sdate.y = item.y;
                this.sdate.m = item.m;
                this.sdate.d = item.d;
                this.$emit("choose", this.sdate, 1);
                this.render();
            }
            else {
                this.sdate.m = item.m;
                this.sdate.y = item.y;
                this.render();
            }
        },
        prev: function () {
            if (this.sdate.m === 0) {
                this.sdate.y--;
                this.sdate.m = 11;
            } else {
                this.sdate.m--;
            }
            this.render();
        },
        switcht: function () {
            this.$emit("switcht", 1);
        },
        next: function () {
            if (this.sdate.m === 11) {
                this.sdate.y++;
                this.sdate.m = 0;
            } else {
                this.sdate.m++;
            }
            this.render();
        },
        settoday: function () {
            this.$emit("settoday");
            this.hide();
            this.render();
        },
        settime: function(){
            this.$emit("switcht", 4);
        },
        clear: function () {
            this.$emit("clear");
            this.hide();
            this.render();
        },
        hide: function () {
            var datepicker = document.getElementById(this.id);
            if (datepicker) { datepicker.style.display = "none"; }
        }
    }
});
Vue.component('datepicker-time', {
    template: `<div class="datepicker-months" style="display: block;"><table class="table-condensed"><thead><tr><th colspan="3"><span @click="choose(00,00,00)" class="month">00:00:00</span></th><th colspan="3"><span @click="choose(23,59,59)" class="month">23:59:59</span></th></tr></thead><tbody><tr><td colspan="2" class="prev"><input class="form-control" type="text" style="width:40px;text-align:center;" maxlength="2" v-model="stime.h"/></td><td colspan="2" class="prev"><input class="form-control" type="text" style="width:40px;text-align:center;" maxlength="2" v-model="stime.mm"/></td><td colspan="2" class="prev"><input class="form-control" type="text" style="width:40px;text-align:center;" maxlength="2" v-model="stime.s"/></td></tr></tbody><tfoot><tr><th colspan="3" class="clear" style="display: table-cell;" @click="choose(99)">确定</th><th colspan="3" class="clear" style="display: table-cell;" @click="back">返回</th></tr></tfoot></table></div>`,
    props: {
        id: { type: String, default: "" },
        sdate: { type: Object, default: { h: 00, mm: 00, s: 00 } }
    },
    data: function () {
        return {
            stime: { h: "00", mm: "00", s: "00" }
        };
    },
    watch: {
        "sdate.h": { handler() { this.render(); }, deep: false },
        "sdate.mm": { handler() { this.render(); }, deep: false },
        "sdate.s": { handler() { this.render(); }, deep: false }
    },
    mounted: function () {
        this.render();
    },
    methods: {
        render: function () {
            this.stime.h = this.zeroPadTime(this.sdate.h, 23);
            this.stime.mm = this.zeroPadTime(this.sdate.mm, 59);
            this.stime.s = this.zeroPadTime(this.sdate.s, 59);
        },
        choose: function (h,mm,s) {
            if(h === 99){
                this.stime.h = this.zeroPadTime(this.stime.h, 23);
                this.stime.mm = this.zeroPadTime(this.stime.mm, 59);
                this.stime.s = this.zeroPadTime(this.stime.s, 59);
            } else {
                this.stime.h = this.zeroPadTime(h, 23);
                this.stime.mm = this.zeroPadTime(mm, 59);
                this.stime.s = this.zeroPadTime(s, 59);
            }
            this.sdate.h = this.stime.h;
            this.sdate.mm = this.stime.mm;
            this.sdate.s = this.stime.s;
            this.$emit("choose", this.sdate, 4);
            this.hide();
        },
        // 时间补零
        zeroPadTime: function(n, max) {
            if (n === undefined || n === null || n === '' || isNaN(n)) {
                // 空格， null, undefined 非数值
                n = 0;
            } else {
                // 数值非法 0~max
                n = parseInt(n);
                if (n < 0) { n = 0; } else if (n > max) { n = max; }
            }
            // 时间补零
            return String(n < 10 ? '0' + n : n);
        },
        back: function () {
            this.$emit("back", 2);
        },
        hide: function () {
            var datepicker = document.getElementById(this.id);
            if (datepicker) { datepicker.style.display = "none"; }
        }
    }
});